package com.ironman.sailboat.mobile.computer.v2;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ironman.sailboat.mobile.context.MockConfigContext;
import com.ironman.sailboat.mobile.threadpool.ThreadPool;
import lombok.extern.slf4j.Slf4j;
import org.dromara.mica.mqtt.codec.MqttQoS;
import org.dromara.mica.mqtt.spring.client.MqttClientTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

@Slf4j
@Configuration
public class TrainComputerConfig {

    @Bean
    public TrainComputer trainComputer(MqttClientTemplate mqttClientTemplate) {

        // 船速刷新阈值  cm/s
        double speedValueRefresh = 0.1 * 51.44;
        // 船速数据量阈值
        int speedCountRefresh = 3;

        // VMG刷新阈值  cm/s
        double vmgValueRefresh = 0.1 * 51.44;
        // VMG数据量阈值
        int vmgCountRefresh = 3;

        // 平衡刷新阈值
        int rolValueRefresh = 2;
        // 平衡数据量阈值
        int rolCountRefresh = 30;
        // 平衡偏离阈值
        int rolBalanceDeviation = 3;

        // 俯仰刷新阈值
        int pitchValueRefresh = 2;
        // 俯仰数据量阈值
        int pitchCountRefresh = 20;
        // 俯仰偏离阈值
        int pitchBalanceDeviation = 3;

        // 航向刷新阈值
        int headingValueRefresh = 2;
        // 航向数据量阈值
        int headingCountRefresh = 3;

        // 船首向刷新阈值
        int yawValueRefresh = 3;
        // 船首向数据量阈值
        int yawCountRefresh = 30;

        // 心率刷新阈值
        int hrValueRefresh = 2;
        // 心率数据量阈值
        int hrCountRefresh = 3;
        // 监测运动员心率的数量
        int hrCount = 2;

        // 逆风时: 标准船速和VMG TODO 航行标准值获取接口
        Function<Double, double[]> standardUFun = windSpeed -> {
            double[] standard;
            if (windSpeed <= 5 * 51.44) {
                standard = new double[]{0.01 * 51.44, 0.01 * 51.44};
            } else if (windSpeed > 5 * 51.44 && windSpeed <= 8 * 51.44) {
                standard = new double[]{4.01 * 51.44, 3.16 * 51.44};
            } else if (windSpeed > 8 * 51.44 && windSpeed <= 12 * 51.44) {
                standard = new double[]{4.48 * 51.44, 3.53 * 51.44};
            } else if (windSpeed > 12 * 51.44 && windSpeed <= 15 * 51.44) {
                standard = new double[]{4.76 * 51.44, 3.75 * 51.44};
            } else {
                standard = new double[]{4.61 * 51.44, 3.64 * 51.44};
            }
            return new double[]{
                    BigDecimal.valueOf(standard[0]).setScale(4, RoundingMode.HALF_UP).doubleValue()
                    , BigDecimal.valueOf(standard[1]).setScale(4, RoundingMode.HALF_UP).doubleValue()};
        };

        // 顺风时: 标准船速和VMG TODO 航行标准值获取接口
        Function<Double, double[]> standardDFun = windSpeed -> {
            double[] standard;
            if (windSpeed <= 5 * 51.44) {
                standard = new double[]{0.01 * 51.44, 0.01 * 51.44};
            } else if (windSpeed > 5 * 51.44 && windSpeed <= 8 * 51.44) {
                standard = new double[]{3.88 * 51.44, 3.75 * 51.44};
            } else if (windSpeed > 8 * 51.44 && windSpeed <= 12 * 51.44) {
                standard = new double[]{5.18 * 51.44, 5.00 * 51.44};
            } else if (windSpeed > 12 * 51.44 && windSpeed <= 15 * 51.44) {
                standard = new double[]{6.90 * 51.44, 6.67 * 51.44};
            } else {
                standard = new double[]{8.87 * 51.44, 8.57 * 51.44};
            }
            return new double[]{
                    BigDecimal.valueOf(standard[0]).setScale(4, RoundingMode.HALF_UP).doubleValue()
                    , BigDecimal.valueOf(standard[1]).setScale(4, RoundingMode.HALF_UP).doubleValue()};
        };

        // UI渲染数据
        Consumer<GeneralTrainData> uiDataConsumer = generalTrainData -> {
            // TODO 渲染UI
        };

        // 通用训练数据每秒回调
        BiConsumer<Date, GeneralTrainData> generalTrainDataConsumer = (ts, generalTrainData) -> {
            generalTrainData.setmHmName(MockConfigContext.toMHmName());
            generalTrainData.setColor(MockConfigContext.toColor());
            String topic = StrUtil.format("mobile/up/general-train/{}/{}/{}", MockConfigContext.toTenantCode(), MockConfigContext.toLevelId(), MockConfigContext.toMHmId());
            JSONObject jsonObject = JSONUtil.createObj();
            jsonObject.set("ts", DateUtil.format(ts, "yyyy-MM-dd HH:mm:ss"));
            jsonObject.set("mHmId", MockConfigContext.toMHmId());
            jsonObject.set("data", JSONUtil.parseObj(JSONUtil.toJsonStr(generalTrainData, JSONConfig.create().setIgnoreNullValue(false)), false));
            ThreadPool.FIXED_EXECUTOR.submit(() -> {
                log.info("{}: {}", topic, JSONUtil.toJsonStr(jsonObject, JSONConfig.create().setIgnoreNullValue(false)));
                mqttClientTemplate.getMqttClient().publish(topic, JSONUtil.toJsonStr(jsonObject, JSONConfig.create().setIgnoreNullValue(false)).getBytes(StandardCharsets.UTF_8), MqttQoS.QOS1);
            });
        };

        return new TrainComputer(
                null, null,
                speedValueRefresh, speedCountRefresh,
                vmgValueRefresh, vmgCountRefresh,
                rolValueRefresh, rolCountRefresh,
                rolBalanceDeviation,
                pitchValueRefresh, pitchCountRefresh,
                pitchBalanceDeviation,
                headingValueRefresh, headingCountRefresh,
                yawValueRefresh, yawCountRefresh,
                hrValueRefresh, hrCountRefresh, hrCount,
                standardUFun, standardDFun,
                uiDataConsumer, generalTrainDataConsumer
        );
    }

}
